import {
  Collection, Db, Document, MongoClient, WithId,
} from 'mongodb';

const url = 'mongodb://localhost:27017';

export default class MongoDBClient {
  static client: MongoClient;

  public static getInstance(): MongoClient {
    if (!MongoDBClient.client) {
      MongoDBClient.client = new MongoClient(url);
    }
    return MongoDBClient.client;
  }

  public static async connect(): Promise<void> {
    try {
      await MongoDBClient.getInstance().connect();
    } catch (error) {
      throw new Error('Error connecting to MongoDB');
    }
  }

  public static async disconnect(): Promise<void> {
    try {
      await MongoDBClient.getInstance().close();
    } catch (error) {
      throw new Error('Error disconnecting from MongoDB');
    }
  }

  public static async getCollection(dbName: string, collectionName: string): Promise<Collection<Document>> {
    try {
      await MongoDBClient.connect();
      const db = MongoDBClient.getInstance().db(dbName);
      return db.collection(collectionName);
    } catch (error) {
      throw new Error('Error getting collection from MongoDB');
    }
  }

  public static async getDatabase(dbName: string): Promise<Db> {
    try {
      await MongoDBClient.connect();
      return MongoDBClient.getInstance().db(dbName);
    } catch (error) {
      throw new Error('Error getting database from MongoDB');
    }
  }

  public static async getDocs(dbName: string, collectionName: string): Promise<WithId<Document>[]> {
    try {
      const collection = await MongoDBClient.getCollection(dbName, collectionName);
      return collection.find({}).toArray();
    } catch (error) {
      throw new Error('Error getting documents from MongoDB');
    }
  }

  public static async addDoc(dbName: string, collectionName: string, doc: Document): Promise<void> {
    try {
      const collection = await MongoDBClient.getCollection(dbName, collectionName);
      await collection.insertOne(doc);
    } catch (error) {
      throw new Error('Error adding document to MongoDB');
    }
  }
}
